package com.education.generator.plugin;


import org.mybatis.generator.api.IntrospectedColumn;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.PluginAdapter;
import org.mybatis.generator.api.dom.java.*;
import org.mybatis.generator.api.dom.xml.Attribute;
import org.mybatis.generator.api.dom.xml.XmlElement;
import org.mybatis.generator.internal.util.StringUtility;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.List;


/**
 * A MyBatis Generator plugin to use Lombok's annotations.
 * For example, use @Data annotation instead of getter ands setter.
 *
 * @author Paolo Predonzani (http://softwareloop.com/)
 */
public class LombokPlugin extends PluginAdapter {

    @Override
    public boolean validate(List<String> list) {
        return true;
    }

    @Override
    public boolean modelBaseRecordClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
        //添加domain的import
        topLevelClass.addImportedType("lombok.Data");
        topLevelClass.addImportedType("lombok.Builder");
        topLevelClass.addImportedType("lombok.NoArgsConstructor");
        topLevelClass.addImportedType("lombok.AllArgsConstructor");
        topLevelClass.addImportedType("com.baomidou.mybatisplus.annotations.TableField");
        topLevelClass.addImportedType("com.baomidou.mybatisplus.annotations.TableId");
        topLevelClass.addImportedType("com.baomidou.mybatisplus.annotations.TableName");
        topLevelClass.addImportedType("com.baomidou.mybatisplus.enums.IdType");
        topLevelClass.addImportedType("com.baomidou.mybatisplus.activerecord.Model");



        //添加domain的注解
        topLevelClass.addAnnotation("@Data");
        topLevelClass.addAnnotation("@Builder");
        topLevelClass.addAnnotation("@NoArgsConstructor");
        topLevelClass.addAnnotation("@AllArgsConstructor");
        String tableName=introspectedTable.getFullyQualifiedTableNameAtRuntime();
        topLevelClass.addAnnotation("@TableName(\"" +tableName+ "\")");


        topLevelClass.addJavaDocLine("/**");
        topLevelClass.addJavaDocLine("* <p>");

        String remarks=introspectedTable.getRemarks();
        if(StringUtility.stringHasValue(remarks)){
//            topLevelClass.addJavaDocLine("/**");
            topLevelClass.addJavaDocLine("*");
            topLevelClass.addJavaDocLine(remarks);
  //          topLevelClass.addJavaDocLine("*/");
        }else{
            topLevelClass.addJavaDocLine(tableName);
        }
        topLevelClass.addJavaDocLine("* </p>");

        //添加domain的注释
//        topLevelClass.addJavaDocLine("/**");
        topLevelClass.addJavaDocLine("* <p>");
        topLevelClass.addJavaDocLine("* Created by aj1g Generator on " + date2Str(new Date()));
//        topLevelClass.addJavaDocLine("");
        topLevelClass.addJavaDocLine("* </p>");

        int cn=introspectedTable.getAllColumns().size();
        String ss_act_colname="";
        String ss_prop_name="";
        String ss_act_mark="";
        String ss_prop_mark="";
        String ss_prop_mark_json="";

        for(int i=0;i<cn;i++){
            ss_act_colname=ss_act_colname+introspectedTable.getAllColumns().get(i).getActualColumnName()+" , ";
            ss_prop_name=ss_prop_name+introspectedTable.getAllColumns().get(i).getJavaProperty()+" , ";
            ss_act_mark=ss_act_mark+introspectedTable.getAllColumns().get(i).getActualColumnName()
                    +"="+"\""+introspectedTable.getAllColumns().get(i).getRemarks()
                    +"/"+introspectedTable.getAllColumns().get(i).getJdbcTypeName()+"\""
                    +" , ";
            ss_prop_mark=ss_prop_mark+introspectedTable.getAllColumns().get(i).getJavaProperty()
                    +"="+"\""+introspectedTable.getAllColumns().get(i).getRemarks()
                    +"/"+introspectedTable.getAllColumns().get(i).getFullyQualifiedJavaType().getShortName()+"\""
                    +" , ";

            ss_prop_mark_json=ss_prop_mark_json+"\""+ introspectedTable.getAllColumns().get(i).getJavaProperty() +"\""
                    +":"+"\""+introspectedTable.getAllColumns().get(i).getRemarks()
                    +"/"+introspectedTable.getAllColumns().get(i).getFullyQualifiedJavaType().getShortName()+"\""
                    +" , ";

        }


        if(ss_act_colname.lastIndexOf(",")>0){
            ss_act_colname="("+ss_act_colname.substring(0,ss_act_colname.lastIndexOf(","))+")";
        }

        if(ss_prop_name.lastIndexOf(",")>0){
            ss_prop_name="("+ss_prop_name.substring(0,ss_prop_name.lastIndexOf(","))+")";
        }

        if(ss_act_mark.lastIndexOf(",")>0){
            ss_act_mark="("+ss_act_mark.substring(0,ss_act_mark.lastIndexOf(","))+")";
        }

        if(ss_prop_mark.lastIndexOf(",")>0){
            ss_prop_mark="("+ss_prop_mark.substring(0,ss_prop_mark.lastIndexOf(","))+")";
        }


        if(ss_prop_mark_json.lastIndexOf(",")>0){
            ss_prop_mark_json="{"+ss_prop_mark_json.substring(0,ss_prop_mark_json.lastIndexOf(","))+"}";
        }


        topLevelClass.addJavaDocLine("* <p>");
        topLevelClass.addJavaDocLine("\n//表 "+tableName+" 字段列表：");
        topLevelClass.addJavaDocLine("* </p>");
        topLevelClass.addJavaDocLine("* <p>");
        topLevelClass.addJavaDocLine(ss_act_colname);
        topLevelClass.addJavaDocLine("* </p>");
        topLevelClass.addJavaDocLine("* <p>");
        topLevelClass.addJavaDocLine("\n//对象 "+topLevelClass.getType().getShortName()+" 属性列表：");
        topLevelClass.addJavaDocLine("* </p>");
        topLevelClass.addJavaDocLine("* <p>");
        topLevelClass.addJavaDocLine(ss_prop_name);
        topLevelClass.addJavaDocLine("* </p>");
        topLevelClass.addJavaDocLine("* <p>");
        topLevelClass.addJavaDocLine("\n//表 "+tableName+" 字段中文解释：");
        topLevelClass.addJavaDocLine("* </p>");
        topLevelClass.addJavaDocLine("* <p>");
        topLevelClass.addJavaDocLine(ss_act_mark);
        topLevelClass.addJavaDocLine("* </p>");
        topLevelClass.addJavaDocLine("* <p>");
        topLevelClass.addJavaDocLine("\n//对象 "+topLevelClass.getType().getShortName()+" 属性解释：");
        topLevelClass.addJavaDocLine("* </p>");
        topLevelClass.addJavaDocLine("* <p>");
        topLevelClass.addJavaDocLine(ss_prop_mark);
        topLevelClass.addJavaDocLine("* </p>");
        topLevelClass.addJavaDocLine("* <p>");
        topLevelClass.addJavaDocLine("\n//对象 "+topLevelClass.getType().getShortName()+" Json格式：");
        topLevelClass.addJavaDocLine("* </p>");
        topLevelClass.addJavaDocLine("* <p>");
        topLevelClass.addJavaDocLine(ss_prop_mark_json);
        topLevelClass.addJavaDocLine("* </p>");


        topLevelClass.addJavaDocLine("\n\n*/\n\n");

        //添加Model接口
        String rootInterface="Model<"+topLevelClass.getType().getShortName()+">";
        topLevelClass.setSuperClass(rootInterface);


        //添加pkVal方法
        Method method = new Method();
        method.setVisibility(JavaVisibility.PUBLIC);
        FullyQualifiedJavaType returnType=new FullyQualifiedJavaType("Serializable");
        method.setReturnType(returnType);

       int cnt=topLevelClass.getFields().size();
        boolean haspkVal=false;
       int i=0;
       while (i<cnt){
           String fn=topLevelClass.getFields().get(i).getName();
           if (fn.contains("guid")) {
               method.addBodyLine(" return this.guid;");
               haspkVal=true;
               break;
           }

           i++;
       }

       if(!haspkVal){
           i=0;
           while (i<cnt){
               String fn=topLevelClass.getFields().get(i).getName();
               if (fn.contains("id")||fn.contains("Id")) {
                   method.addBodyLine(" return this."+fn+";");
                   break;
               }

               i++;
           }

       }

        method.addAnnotation("@Override");
        method.setName("pkVal");
        topLevelClass.addMethod(method);

        return true;
    }

   @Override
    public boolean modelRecordWithBLOBsClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
       topLevelClass.addImportedType("com.baomidou.mybatisplus.annotations.TableField");
       topLevelClass.addImportedType("com.baomidou.mybatisplus.annotations.TableName");
       topLevelClass.addImportedType("lombok.Data");
      // topLevelClass.addImportedType("lombok.Builder");
       topLevelClass.addImportedType("lombok.NoArgsConstructor");
       topLevelClass.addImportedType("lombok.AllArgsConstructor");

       String remarks=introspectedTable.getRemarks();
       if(StringUtility.stringHasValue(remarks)){
           topLevelClass.addJavaDocLine("/**");
           topLevelClass.addJavaDocLine("*");
           topLevelClass.addJavaDocLine(remarks);
           topLevelClass.addJavaDocLine("*/");
       }

       //添加domain的注解
       topLevelClass.addAnnotation("@Data");
     //  topLevelClass.addAnnotation("@Builder");
       topLevelClass.addAnnotation("@NoArgsConstructor");
       topLevelClass.addAnnotation("@AllArgsConstructor");
       String tableName=introspectedTable.getFullyQualifiedTableNameAtRuntime();
       topLevelClass.addAnnotation("@TableName(\"" +tableName+ "\")");

       //添加domain的注释
       topLevelClass.addJavaDocLine("/**");
       topLevelClass.addJavaDocLine("* Created by Mybatis Generator on " + date2Str(new Date()));
       topLevelClass.addJavaDocLine("*/");


        return true;
    }




    @Override
    public boolean modelSetterMethodGenerated(Method method, TopLevelClass topLevelClass, IntrospectedColumn introspectedColumn, IntrospectedTable introspectedTable, ModelClassType modelClassType) {
        //不生成getter
        return false;
    }

    @Override
    public boolean modelGetterMethodGenerated(Method method, TopLevelClass topLevelClass, IntrospectedColumn introspectedColumn, IntrospectedTable introspectedTable, ModelClassType modelClassType) {
        //不生成setter
        return false;
    }

    private String date2Str(Date date) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
        return sdf.format(date);
    }




    @Override
    public boolean clientGenerated(Interface interfaze, TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
        //Mapper文件的注释
        interfaze.addJavaDocLine("/**");
        interfaze.addJavaDocLine("* Created by Mybatis Generator on " + date2Str(new Date()));
        interfaze.addJavaDocLine("*/");

        //添加BaseMapper接口
        FullyQualifiedJavaType fqj_it=new FullyQualifiedJavaType("com.baomidou.mybatisplus.mapper.BaseMapper");
        interfaze.addImportedType(fqj_it);

        FullyQualifiedJavaType fqj_it2=new FullyQualifiedJavaType("org.springframework.stereotype.Repository");
        interfaze.addImportedType(fqj_it2);

        interfaze.addAnnotation("@Repository");


        String rootClass = interfaze.getType().getShortName();
        if(interfaze.getType().getShortName().lastIndexOf("Mapper")>0) {
            rootClass = interfaze.getType().getShortName().substring(0, interfaze.getType().getShortName().lastIndexOf("Mapper"));
        }

        for (Iterator iter = interfaze.getImportedTypes().iterator(); iter.hasNext();) {
            FullyQualifiedJavaType fqj = (FullyQualifiedJavaType)iter.next();
            String tmpclass=fqj.getShortName();
            if(tmpclass.contains("WithBLOBs") && (tmpclass.contains(rootClass))){
                if(tmpclass.lastIndexOf(".")>0) {
                    rootClass = tmpclass.substring(tmpclass.lastIndexOf("."));
                }
                else{
                    rootClass=tmpclass;
                }
                break;
            }

        }



        String rootInterface="BaseMapper<"+rootClass+">";
        FullyQualifiedJavaType fqj2=new FullyQualifiedJavaType(rootInterface);
        interfaze.addSuperInterface(fqj2);

        return true;
    }


    @Override
    public boolean clientInsertMethodGenerated(Method method, Interface interfaze, IntrospectedTable introspectedTable) {
        method.setName("insertData");
        return true;
    }

    @Override
    public boolean sqlMapInsertElementGenerated(XmlElement element, IntrospectedTable introspectedTable) {


        int cnt=element.getAttributes().size();
        int i=0;
        while(i<cnt){
            if("id".equalsIgnoreCase(element.getAttributes().get(i).getName())){
                element.getAttributes().remove(i);
                break;
            }
        }

        Attribute attr=new Attribute("id","insertData");

        element.addAttribute(attr);

        return true;
    }

}
